/*
JavaScript ES6的Map类有以下常见方法：
-  clear() ：删除Map中的所有键值对
-  delete(key) ：从Map中删除指定键的值
-  entries() ：返回Map对象中所有键值对的数组
-  forEach(callbackFn, thisArg) ：以插入顺序执行给定的回调函数
-  get(key) ：获取指定键的值
-  has(key) ：如果Map中存在指定键则返回 true ，否则返回 false
-  keys() ：返回Map对象中所有键的数组
-  set(key, value) ：向Map对象添加键值对
-  size ：返回Map对象中键值对的数量
-  values() ：返回Map对象中所有值的数组

除此之外，Map类还提供了 Symbol.iterator 属性，可以用于使用 for...of 循环遍历Map对象中的键值对。
 */
class MyMap {
    constructor(iterable = []) {
        //? 验证是否是可迭代的对象 Symbol.iterator  是一个内置的 Symbol 类型常量，它定义了一个默认的迭代器函数。当一个对象实现了Symbol.iterator方法时，该对象就是可迭代的
        //? iterable[Symbol.iterator]如果iterable是一个可迭代对象则会返回迭代器否则返回undefined
        if (typeof iterable[Symbol.iterator] !== "function") {
            throw new TypeError(`你提供的${iterable}不是一个可迭代的对象`)
        }
        this._datas = [];
        for (const item of iterable) {
            //? item 也得是一个可迭代对象
            if (typeof item[Symbol.iterator] !== "function") {
                throw new TypeError(`你提供的${item}不是一个可迭代的对象`);
            }
            const iterator = item[Symbol.iterator]();
            //? 不一定是数组，所以用这种方式(数组这样也行啊)
            const key = iterator.next().value;
            const value = iterator.next().value;
            this.set(key, value);
        }

    }

    set(key, value) {
        //? 找到这个key
        const obj = this._getObj(key);
        if (obj) {//已经有了就是要修改
            //修改
            obj.value = value;
        }
        else {//? 没有的话添加
            this._datas.push({
                key,
                value
            })
        }
    }

    get(key) {
        const item = this._getObj(key);
        if (item) {
            return item.value;
        }
        return undefined;// 找不到
    }

    size() {
        return this._datas.length;
    }

    delete(key) {
        for (let i = 0; i < this._datas.length; i++) {
            const element = this._datas[i];
            if (this.isEqual(element.key, key)) {
                this._datas.splice(i, 1);
                return true;
            }
        }
        return false;
    }

    clear() {
        this._datas.length = 0;
    }

    /**
     * 根据key值从内部数组中，找到对应的数组项
     * @param {*} key
     */
    _getObj(key) {
        for (const item of this._datas) {
            if (this.isEqual(item.key, key)) {
                return item;
            }
        }
    }

    has(key) {
        return this._getObj(key) !== undefined;
    }

    /**
     * 判断两个数据是否相等
     * @param {*} data1
     * @param {*} data2
     */
    isEqual(data1, data2) {
        if (data1 === 0 && data2 === 0) {
            return true;
        }
        // 返回值是布尔
        return Object.is(data1, data2);
    }

    *[Symbol.iterator]() {//迭代器创建函数本身就是生成器函数  *
        for (const item of this._datas) {
            yield [item.key, item.value];
        }
    }

    forEach(callback) {
        for (const item of this._datas) {
            callback(item.value, item.key, this);
        }
    }
}
let map = new MyMap( [['a','1'], 'b', ['d','c']])
console.log(map.get('a'));
